/*
  这个服务是将新增页面中的加减项中所需方法抽离出来，本来这种功能更适合在 class 基类中来完成；
  但是不是所有的页面都需要这部分功能，并且各个基类的所在文件层级不同，综合考虑，使用 service 来做这个抽离；
  在调用时，只需要在目标组件初始化时执行 init(func, obj, dataArr) 方法，
  func 是生成校验规则的方法，obj 是实例，dataArr 是传入的已存在的数据.
*/
import { Injectable } from '@angular/core'
import { FormGroup, FormBuilder } from '@angular/forms'
import { ExchangeRate, ALPChannel, QrChannel } from '@shared/interfaces/acquirer'
import { deepCopy } from '@delon/util'
import { User } from '@shared/interfaces/user'
import { AddMinusService } from './addMinus.service'
import { IFormItem, ChanCodeValue } from '@shared/interfaces/common'
import { makeAllControlDirty, encryptLongText, numScale } from 'app/utils/helpers'
import { EPaymentBrand } from '@shared/enums'
import { CommonAcquirerService } from './acquirer.service'

@Injectable()
export class ChannelAddMinusService extends AddMinusService {
  validateForms: FormGroup[] = []

  formItemsArr: IFormItem[][] = []

  validateRules: { [key: string]: any }

  isNeedValidateArr: boolean[] = []

  generateFunc: () => any[]

  obj: ExchangeRate | User

  constructor(public fb: FormBuilder, public commonAcquirerService: CommonAcquirerService) {
    super(fb)
  }

  get values(): any[] {
    return this.validateForms.map(form => form.value)
  }

  get valid(): boolean {
    let isValid = true
    this.validateForms.forEach((form, index) => {
      if (!this.isNeedValidateArr[index]) return
      if (!form.valid) {
        isValid = false
      }
    })
    return isValid
  }

  init(func, obj, dataArr) {
    this.generateFunc = func
    this.obj = obj
    dataArr.length > 0 ? dataArr.forEach(data => this.generateForm(data)) : this.generateForm(deepCopy(this.obj))
  }

  generateForm(data) {
    const { rule, formItems } = this.generateFunc.call(this, data)
    const validateForm = this.generateValidateForm(rule)
    this.formItemsArr.push(formItems)
    if (data.chanCode === ChanCodeValue.ALP) {
      this.initSwitches(data, formItems) // switch 开关及其控制项,当前只有支付宝需要
    }
    this.validateForms.push(validateForm)
    this.isNeedValidateArr.push(true)
    if (data.isLoaded) {
      /** 当渠道是捕获进来的情况，使用 loadChannel 处理 */
      this.loadChannel(data)
    }
  }

  loadChannel(channel: QrChannel, index?: number): void {
    if (channel.privateKey) channel['privateKeyArray'] = encryptLongText(channel.privateKey)
    index = typeof index === 'number' ? index : this.validateForms.length - 1
    const validateForm = this.validateForms[index]
    for (const key in channel) {
      if (key === 'chanCode' || key === 'chanMerID') {
        continue
      }
      if (validateForm.get(key)) {
        if (key === 'fee') {
          validateForm.get(key).setValue(numScale(channel[key], 2))
          continue
        }
        validateForm.get(key).setValue(channel[key])
      }
    }
    validateForm.get('isLoaded').setValue(true) // 是加载进来的渠道，设置该值
    /** 支付宝渠道比较特殊，SFTP 和 switch 需要特别处理一下 */
    if (channel.chanCode === EPaymentBrand.Alipay) {
      this.specialHandle(channel as ALPChannel, validateForm)
    }

    this.formItemsArr[index].forEach(item => {
      if (item.formControlName !== 'chanCode') item['disable'] = true
    })
    this.isNeedValidateArr[index] = false
  }

  specialHandle(channel: ALPChannel, validateForm: FormGroup) {
    const { sftp, settleCurrency, signKey, appID, publicKey, privateKeyArray } = channel
    if (!sftp || !sftp.username) {
      return
    }
    validateForm.get('sftpUsername').setValue(sftp.username)
    validateForm.get('sftpFilePath').setValue(sftp.filePath)
    if (settleCurrency) {
      validateForm.get('isSupportSettleCurr').setValue(true)
    }
    if (signKey) {
      validateForm.get('isSupportPayment').setValue(true)
    }
    if (appID && publicKey && privateKeyArray) {
      validateForm.get('isSupportPreAuth').setValue(true)
    }
  }

  initSwitches(data, formItems: IFormItem[]): void {
    if (data.signKey) {
      formItems.find(item => item.formControlName === 'signKey').asyncHidden.next(false)
    }
    if (data.settleCurrency) {
      formItems.find(item => item.formControlName === 'settleCurrency').asyncHidden.next(false)
    }
    if (data.appID) {
      formItems.find(item => item.formControlName === 'appID').asyncHidden.next(false)
    }
  }

  generateValidateForm(rule: [{ [key: string]: string }, { [key: string]: string }]): FormGroup {
    return this.fb.group(rule[0], rule[1])
  }

  makeDirty(): void {
    this.validateForms.forEach((form, index) => {
      if (this.isNeedValidateArr[index]) {
        makeAllControlDirty(form)
      }
    })
  }

  /** 检测 chanMerID 的唯一性 */
  checkChanMerIDUnique(
    index: number,
    chanMerID: string,
    key: string = 'chanMerID',
    paymentBrand: string = 'chanCode',
  ): boolean {
    const chanCode = this.validateForms[index].get(paymentBrand).value
    let unique = true
    this.validateForms.forEach((form, i) => {
      if (i === index) return
      if (form.get(paymentBrand).value === chanCode && form.get(key).value === chanMerID) {
        unique = false
      }
    })

    /** 已经存在的渠道 */
    const viewingAcquirerChannels = this.commonAcquirerService.viewingAcquirer.qrChannels
    viewingAcquirerChannels.forEach(channel => {
      if (channel.chanCode === chanCode && channel.chanMerID === chanMerID) {
        unique = false
      }
    })
    if (!unique) {
      this.validateForms[index].get(key).setErrors({ existed: true })
    } else {
      this.validateForms[index].get(key).setErrors(null)
    }
    return unique
  }

  addItem(): void {
    this.generateForm(deepCopy(this.obj))
  }

  minusItem(index: number) {
    if (this.validateForms.length === 0) {
      return
    }
    this.removeItem(index)
  }

  removeItem(index: number) {
    if (this.validateForms.length === 0) return
    this.validateForms.forEach((form, i) => {
      if (i === index) {
        this.validateForms.splice(i, 1)
      }
    })
    this.formItemsArr.forEach((formItem, i) => {
      if (i === index) {
        this.formItemsArr.splice(i, 1)
      }
    })
    this.isNeedValidateArr.forEach((isNeed, i) => {
      if (i === index) {
        this.isNeedValidateArr.splice(i, 1)
      }
    })
  }
}
